package reflect_util

import (
	"fmt"
	"reflect"
	"strings"
	"unicode"
)

func GetAllFieldsOfStruct(q interface{}) (fieldNames []string, fieldValues []interface{}) {
	value := reflect.ValueOf(q)
	if reflect.Struct != value.Kind() {
		fmt.Printf("unsupported type:%s\n", value.Kind())
		return
	}

	for i := 0; i < value.NumField(); i++ {
		field := value.Type().Field(i)
		fieldName := field.Name
		fieldNames = append(fieldNames, fieldName)
		fieldValue := value.FieldByName(fieldName).Interface()
		fieldValues = append(fieldValues, fieldValue)
	}
	return
}

//func ReflectEqual(x, y interface{}) (equal bool) {
//
//	v1 := reflect.ValueOf(x)
//	v2 := reflect.ValueOf(y)
//	type1 := v1.Type()
//	type2 := v2.Type()
//	if type1 != type2 {
//		return false
//	}
//
//	switch x.(type) {
//	case int:
//		equal = y.(int) == y.(int)
//	case string:
//		equal = y.(string) == y.(string)
//	default:
//		equal = reflect.DeepEqual(x, y)
//	}
//	return
//}

func ReflectSetFieldValue(o interface{}, fieldName string, value interface{}) {
	pp := reflect.ValueOf(o) // 取得struct变量的指针
	fieldName = Case2Camel(fieldName)
	field := pp.Elem().FieldByName(fieldName) //获取指定Field  pp.Elem().FieldByName(fieldName)

	k := field.Kind()
	switch k {
	case reflect.String:
		field.SetString(value.(string)) // 设置值 "gerrylon"
	case reflect.Int:
		field.SetInt(int64(value.(int)))
	case reflect.Bool:
		field.SetBool(value.(bool))
	case reflect.Float64:
		field.SetFloat(value.(float64))
	case reflect.Float32:
		field.SetFloat(float64(value.(float32)))
	}
}

func ReflectGetFieldValue(o interface{}, fieldName string) (value interface{}) {
	v := reflect.ValueOf(o)
	fieldName = Case2Camel(fieldName)
	value = v.Elem().FieldByName(fieldName).Interface()
	return
}

// 下划线写法转为驼峰写法
func Case2Camel(name string) string {
	name = strings.Replace(name, "_", " ", -1)
	name = strings.Title(name)
	return strings.Replace(name, " ", "", -1)
}

// 驼峰写法转为下划线写法
func Camel2Case(name string) string {
	result := ""
	for index, c := range name {
		if unicode.IsUpper(c) {
			if index > 0 {
				result += "_"
			}
			result += string(unicode.ToLower(c))
		} else {
			result += string(c)
		}
	}
	return result
}
